package api

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"seat-service/response"
	service "seat-service/service/impl"
	"strconv"
	"time"
)

var classroomService service.ClassroomService

type ClassroomApi struct {
}

func (*ClassroomApi) GetByBuildingAndName(c *gin.Context) {
	par := dto.ClassroomLike{}
	if err := c.ShouldBind(&par); err != nil {
		initialization.SeatLogger.Error("c.ShouldBind(par) failed", zap.Error(err))
		resp.Fail(c, response.CodeParamError, nil)
		return
	}
	classroom, err := classroomService.GetByBuildingAndName(par)
	if err != nil {
		initialization.SeatLogger.Error("classroomService.GetByBuildingAndName(par) failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	resp.Success(c, response.CodeSuccess, classroom)
}

func (*ClassroomApi) GetFreeSeatByStartTime(c *gin.Context) {
	par := &dto.ClassroomRequest{}
	if err := c.ShouldBind(par); err != nil {
		initialization.SeatLogger.Error("c.ShouldBind(par) failed", zap.Error(err))
		resp.Fail(c, response.CodeParamError, nil)
		return
	}
	classrooms, err := classroomService.GetByBuildingID(par.BuildingID)
	if err != nil {
		initialization.SeatLogger.Error("classroomService.GetByBuildingIDAndPage(par.BuildingID, page) failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	// 查询每个教室这个时间的剩余空位
	reserve := model.Reserve{}
	for i, _ := range classrooms {
		reserve.ClassroomID = classrooms[i].ID
		clashReserve, err := reserveService.QueryClashByTime(reserve, par.Time)
		if err != nil {
			initialization.SeatLogger.Error("reserveService.QueryTime(reserve) failed", zap.Error(err))
			resp.Fail(c, response.CodeServerBusy, nil)
			continue
		}
		classrooms[i].FreeSeat = classrooms[i].Seating - len(clashReserve)
	}
	response.Success(c, response.CodeSuccess, classrooms)
}

// GetSeatByIdAndStartEndTime 通过教室id,开始时间，结束时间获取座位
func (*ClassroomApi) GetSeatByIdAndStartEndTime(c *gin.Context) {

	//par := &dto.ParamReserve{}

	par := dto.ParamTimestamp{}
	if err := c.ShouldBindJSON(&par); err != nil {
		initialization.SeatLogger.Error("c.ShouldBind(par) failed", zap.Error(err))
		resp.Fail(c, response.CodeParamError, nil)
		return
	}

	// 拿到教室详细信息
	class, err := classroomService.GetById(par.ClassroomID)
	if err != nil {
		initialization.SeatLogger.Error("classroomService.GetById(par.ID failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	// 查询该教室选择时间段内的所有预约
	reserve, err := reserveService.GetByReserveParam(par)
	if err != nil {
		initialization.SeatLogger.Error("reserveService.GetByReserveParam(par) failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	data, _ := seatService.GetByClassroomID(class.ID) // 状态 0 可选 1 部分可选 2 不可选

	flag := map[uint]int{}
	for _, v := range reserve {
		for i := range par.Times {
			s := time.Unix(par.Times[i].Start, 0)
			e := time.Unix(par.Times[i].End, 0)
			// 部分可选
			if (v.AppointmentTimeStart.After(s) && v.AppointmentTimeStart.Before(e)) || (v.AppointmentTimeEnd.After(s) && v.AppointmentTimeEnd.Before(e)) {
				flag[v.SeatId] += 1
			} else if s.After(v.AppointmentTimeStart) || s.Equal(v.AppointmentTimeStart) && v.AppointmentTimeEnd.After(e) || v.AppointmentTimeEnd.Equal(e) { // 不可选
				flag[v.SeatId] += 2
			} // 剩下的都是可选的
		}
		for i, seat := range data {
			if seat.SeatStatus != 0 { // 损坏或禁用
				data[i].Statue = 2
				continue
			}

			if flag[seat.ID] > 0 && flag[seat.ID] < 2*len(par.Times) {
				data[i].Statue = 1
			} else if flag[seat.ID] == 2*len(par.Times) {
				data[i].Statue = 2
			}
		}
	}
	resp.Success(c, response.CodeSuccess, data)
}

// GetByBuildingID 通过教学楼id获取教室
func (*ClassroomApi) GetByBuildingID(c *gin.Context) {
	par := c.Query("building_id")
	bID, _ := strconv.Atoi(par)
	data, err := classroomService.GetByBuildingID(uint(bID))
	if err != nil {
		initialization.SeatLogger.Error("classroomService.GetByBuildingID(uint(bID)) failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	resp.Success(c, response.CodeSuccess, data)
}

func (*ClassroomApi) GetAll(c *gin.Context) {
	data, err := classroomService.GetAll()
	if err != nil {
		initialization.SeatLogger.Error("classroomService.GetAll() failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	resp.Success(c, response.CodeSuccess, data)
}

func (*ClassroomApi) GetReserveByClassroomStatue(c *gin.Context) {
	par := c.Query("statue")
	status, _ := strconv.Atoi(par)
	data, err := classroomService.GetReserveByClassroomStatue(status)
	if err != nil {
		initialization.SeatLogger.Error("reserveService.GetReserveByClassroomStatue(status) failed", zap.Error(err))
		resp.Fail(c, response.CodeServerBusy, nil)
		return
	}
	resp.Success(c, response.CodeSuccess, data)
}
